<template>
  <div class="portal-list-filter-options full-width">
    <div
      v-if="hasKw && !bottomKw"
      class="key-word part">
      <kw-comp :data="kw || kwValue" @search="kw=$event;search()"></kw-comp>
    </div>
    <div
      v-if="localOpts && localOpts.length"
      class="options part">
      <opt-comp
        v-for="(opt, idx) in localOpts" :key="idx"
        :data="opt"
        :selected="selectedFilters[idx]"
        @select="selectFilter(idx, $event)"
      ></opt-comp>

      <div
        v-if="this.maxLines && this.opts.length > this.maxLines"
        class="show-more-btn full-width row justify-center q-my-sm">
        <q-btn
          class=""
          flat
          :label="showMore ? $t('更少筛选条件') : $t('更多筛选条件')"
          :icon-right="showMore ? 'expand_less' : 'expand_more'"
          @click="showMore = !showMore"
        ></q-btn>
      </div>
    </div>
    <div
      v-if="hasKw && bottomKw"
      class="key-word part">
      <kw-comp @search="kw=$event;search()"></kw-comp>
    </div>
    <div
      class="selected-labbels part row full-width no-wrap items-center"
      v-if="showSelected && selectedLabels?.length">
      <div class="row text-no-wrap">
        {{$t('已选条件')}}:
      </div>
      <div class="selected-labels-list row">
        <q-chip
          class="selected-labels-label"
          v-for="(chip, idx) in selectedLabels" :key="idx"
          :square="true"
          :removable="true"
          @remove="removeSelected(idx)"
        >
        {{$t(chip.label)}}
        </q-chip>
      </div>
      <q-space></q-space>
      <q-btn
        flat class="clear-btn text-no-wrap"
        :label="$t('清空')"
        @click="clearFilters(true)"
      ></q-btn>
    </div>
  </div>
</template>

<script>
import { QBtn, QInput } from 'quasar';

const kwComp = {
  props: {
    data: String,
  },
  data() {
    return {
      kw: '',
      kwChanged: false,
    };
  },
  created() {
    this.kw = this.data || '';
  },
  watch: {
    data() {
      this.kw = this.data || '';
    },
  },
  methods: {
    searchClicked() {
      if (!this.kwChanged) return;

      const kw = (this.kw || '').trim();

      this.$emit('search', kw);
      this.kwChanged = false;
    },
  },
  render(h) {
    return h('div', {
      class: 'row full-width no-wrap items-center',
    }, [
      h(QInput, {
        class: 'col q-pr-sm',
        props: {
          value: this.kw,
          dense: true,
          outlined: true,
        },
        attrs: {
          placeholder: this.$t('请输入关键字'),
        },
        on: {
          input: (v) => {
            this.kw = v;
            this.kwChanged = true;
          },
          keydown: (e) => {
            if (e.code === 'Enter') {
              this.searchClicked();
            }
          },
        },
      }),
      h(QBtn, {
        props: {
          color: 'primary',
          dense: true,
          flat: true,
          label: this.$t('查询'),
          icon: 'search',
        },
        on: {
          click: this.searchClicked,
        },
      }),
    ]);
  },
};

const optComp = {
  props: {
    data: Object,
    selected: Array,
  },
  data() {
    return {
      localSelected: [],
      localRanges: [],
    };
  },
  created() {
    [this.localSelected, this.localRanges] = this.polish(this.selected || []);
  },
  watch: {
    selected(v) {
      [this.localSelected, this.localRanges] = this.polish(v || []);
    },
  },
  methods: {
    polish(d) {
      if (!this.data || !this.data.options || this.data.options.length <= 0) return [];

      const ret = [];
      const ranges = [];
      this.data.options.forEach((opt, idx) => {
        if (opt.range) {
          ranges[idx] = d[idx] || {};
          ranges[idx].min = ranges[idx].min || undefined;
          ranges[idx].max = ranges[idx].max || undefined;

          ret[idx] = d[idx] || undefined;
        } else {
          ret[idx] = d[idx] || undefined;
        }
      });
      return [ret, ranges];
    },
  },
  render(h) {
    const submitRange = (idx) => {
      if (!this.localRanges || !this.localRanges[idx]
        || (!this.localRanges[idx].min && !this.localRanges[idx].max)) return;

      let localSelected = [];
      if (!this.data.multiple) {
        localSelected[idx] = this.localRanges[idx];
      } else {
        localSelected[idx] = this.localRanges[idx];
        localSelected = Object.merge(this.localSelected, localSelected);
      }

      this.$emit('select', localSelected);
    };

    return h('div', {
      class: 'row full-width no-wrap',
    }, [
      h('div', {
        class: 'filter-label q-mr-sm q-py-xs',
        style: 'min-width: 80px; text-align: right;',
      }, `${this.$t(this.data.label)}: `),
      h('div', {
        class: 'filter-options-option row items-center q-px-xs cursor-pointer text-no-wrap',
      }, [h('span', {
        class: `unlimited option q-my-xs q-px-sm ${(!this.selected || (this.selected && this.selected.filter((opt) => !!opt).length <= 0)) ? 'active' : ''}`,
        on: {
          click: () => {
            this.$emit('select', []);
          },
        },
      }, this.$t('不限'))]),
      h('div', {
        class: 'row filter-options',
      }, (this.data.options || []).map((opt, idx) => {
        if (opt.range) {
          return h('div', {
            class: 'filter-options-option row no-wrap items-center q-mx-sm q-py-xs',
          },
          [h('div', {
            class: `row no-wrap items-center option q-my-xs q-px-sm ${(this.selected && this.selected[idx] && (this.selected[idx].min || this.selected[idx].max)) ? 'active' : ''}`,
          }, [
            h(QInput, {
              style: 'height: 16px; width: 60px;font-size:12px;',
              props: {
                value: this.localRanges && this.localRanges[idx] && this.localRanges[idx].min,
                dense: true,
                outlined: true,
              },
              attrs: {
                placeholder: opt.start && opt.start.placeholder,
              },
              on: {
                input: (v) => {
                  this.localRanges[idx].min = Number(v);
                },
                keydown: (e) => {
                  if (e.code === 'Enter') {
                    submitRange(idx);
                  }
                },
              },
            }),
            h('span', {
              class: 'q-px-xs',
            }, '~'),
            h(QInput, {
              style: 'height: 16px; width: 60px;font-size:12px;',
              props: {
                value: this.localRanges && this.localRanges[idx] && this.localRanges[idx].max,
                dense: true,
                outlined: true,
              },
              attrs: {
                placeholder: opt.end && opt.end.placeholder,
              },
              on: {
                input: (v) => {
                  this.localRanges[idx].max = Number(v);
                },
                keydown: (e) => {
                  if (e.code === 'Enter') {
                    submitRange(idx);
                  }
                },
              },
            }),
            opt.unit ? h('span', {
              class: 'q-px-xs',
            }, opt.unit) : undefined,
            h(QBtn, {
              props: {
                label: this.$t('确认'),
                dense: true,
                flat: true,
                size: 'md',
                color: 'primary',
              },
              on: {
                click: () => {
                  submitRange(idx);
                },
              },
            }),
          ])]);
        }

        return h('div', {
          class: 'filter-options-option row items-center cursor-pointer q-mx-xs',
          on: {
            click: () => {
              this.$set(this.localSelected, idx, !this.localSelected[idx]);

              let localSelected = [];
              if (!this.data.multiple) {
                localSelected[idx] = this.localSelected[idx];
              } else {
                localSelected = this.localSelected;
              }

              this.$emit('select', localSelected);
            },
          },
        }, [h('span', {
          class: `option q-my-xs q-px-sm ${(this.selected && this.selected[idx]) ? 'active' : ''}`,
        }, this.$t(opt.label))]);
      })),
    ]);
  },
};

export default {
  name: 'PortalListFilterOptions',
  props: {
    opts: {
      type: Array,
      default: () => [],
    },
    hasKw: Boolean,
    kwValue: String,
    bottomKw: Boolean,
    showSelected: {
      type: Boolean,
      default: true,
    },
    maxLines: {
      type: Number,
      default: 0,
    },
  },
  components: {
    kwComp,
    optComp,
  },
  data() {
    return {
      kw: '',
      data: {},
      showMore: false,
      selectedFilters: [],
    };
  },
  computed: {
    localOpts() {
      if (this.maxLines && !this.showMore) {
        return this.opts.filter(
          (opt) => !!opt && opt.options && opt.options.length,
        ).slice(0, this.maxLines);
      }

      return this.opts;
    },
    selectedLabels() {
      const ret = [];

      (this.selectedFilters || []).forEach((sf, fidx) => {
        (sf || []).forEach((sfo, oidx) => {
          if (!this.opts[fidx].options[oidx]) return;

          if (sfo === true) {
            ret.push({ label: this.opts[fidx].options[oidx].label, pos: [fidx, oidx] });
          } else if (sfo && this.opts[fidx].options[oidx].range && (sfo.min || sfo.max)) {
            ret.push({
              label: `${sfo.min || ''}~${sfo.max || ''}${this.opts[fidx].options[oidx].unit || ''}`,
              pos: [fidx, oidx],
            });
          }
        });
      });

      if (this.kw.trim()) {
        ret.push({
          label: this.kw,
          pos: 'kw',
        });
      }

      return ret;
    },
  },
  watch: {
    // selectedFilters() {
    //   this.search();
    // },
    // kw() {
    //   this.search();
    // },
  },
  methods: {
    generateFilters() {
      const ret = {};

      (this.selectedFilters || []).forEach((sf, fidx) => {
        const { multiple, field, options } = this.opts[fidx];
        if (!field) return;

        const filter = {};
        filter[field] = [];

        (sf || []).forEach((sfo, oidx) => {
          const { range, value } = options[oidx];

          if (sfo === true) {
            if (multiple) {
              filter[field].push(typeof value === 'function' ? value() : value);
            } else {
              filter[field][0] = typeof value === 'function' ? value() : value;
            }
          } else if (range && sfo && (sfo.min || sfo.max)) {
            const rangeVal = typeof value === 'function' ? value(sfo.min, sfo.max) : `${typeof sfo.min === 'number' ? sfo.min : ''}~${typeof sfo.max === 'number' ? sfo.max : ''}`;
            if (multiple) {
              filter[field].push(rangeVal);
            } else {
              filter[field][0] = rangeVal;
            }
          }
        });

        filter[field] = filter[field].join(',');

        if (filter[field]) {
          Object.assign(ret, filter);
        }
      });

      if (this.kw.trim()) {
        ret.kw = this.kw.trim();
      }

      return ret;
    },
    search() {
      this.$emit('search', this.generateFilters());
    },
    selectFilter(idx, selected) {
      this.$set(this.selectedFilters, idx, Object.clone(selected));

      // this.selectedFilters[idx] = Object.clone(selected);

      this.search();
    },
    removeSelected(idx) {
      const fidx = this.selectedLabels[idx]
        && this.selectedLabels[idx].pos
        && this.selectedLabels[idx].pos[0];
      const oidx = this.selectedLabels[idx]
        && this.selectedLabels[idx].pos
        && this.selectedLabels[idx].pos[1];

      if (this.selectedLabels[idx] && this.selectedLabels[idx].pos === 'kw') {
        this.kw = '';
        return;
      }

      if (typeof fidx !== 'number' || typeof oidx !== 'number') return;

      this.$set(this.selectedFilters[fidx], oidx, undefined);

      // this.selectedFilters[fidx][oidx] = undefined;
      this.search();
    },
    clearFilters(refresh = false) {
      // this.selectFilters = [];
      this.$set(this, 'selectedFilters', []);
      this.kw = '';

      if (refresh) {
        this.search();
      }
    },
  },
};
</script>

<style lang="sass" scoped>
.portal-list-filter-options
  .part
    background: $background
    border-radius: 5px
    margin-bottom: 1px
    padding: 16px 16px
    .show-more-btn
      opacity: 0.6
    :deep(.filter-options-option)
      height: 30px
      margin-bottom: 12px
      .option
        border: 1px solid transparent
        border-radius: 5px
        &.active
          border-color: $primary
      .q-field__control
        height: 16px
</style>
